/*
 *  $Id: EnchantmentCard.cs 1221 2010-11-30 16:54:52Z thenn.erannor $
 *	This file is a part of Ragima CCG.
 *	(C) 2008-2009 Ragima development group.
 *
 *	Licensed under the terms of the GNU GPL License version 2.
 *
 */

using System;
using System.Collections.Generic;

using AgateLib.Geometry;

namespace Ragima {
    /// <summary>
    /// Карта чар.
    /// Полностью как заклинание, но после использования не возвращается в колоду.
    /// </summary>
    public abstract class EnchantmentCard: SpellCard {
        public EnchantmentCard(string id): base(id) {}

        public override CardType CardType {
            get { return CardType.Enchantment; }
        }

        protected override int GetWeight() {
            int weight = base.GetWeight();
            Affect affect = CreateEnchantment();
            if (affect != null) weight += affect.GetWeight(this);
            return weight;
        }

        public sealed override CardPlace PlaceAfterUse { get { return CardPlace.None; } }

        public virtual AbstractObject GetTarget(TargetArgs args) {
            return null;
        }

        protected virtual EnchantmentAffect CreateEnchantment() {
            return null;
        }

        public override void DoAction(TargetArgs args) {
            AbstractObject target = GetTarget(args);
            if (target == null) return;
            EnchantmentAffect enchantment = CreateEnchantment();
            if (enchantment == null) return;
            enchantment.SetData(args.Player, this);
            target.AddAffect(enchantment);
        }

        public override bool DrawHelp(int x, int y) {
            bool draw = base.DrawHelp(x, y);
            if (draw) DrawIcons(new Point(x+22, y+31));
            return draw;
        }

        private AffectIconDictionary _icons;
        private AffectIconItems _items;

        private void DrawIcons(Point start) {
            if (_icons == null) {
                EnchantmentAffect affect = CreateEnchantment();
                if (affect == null) return;
                _icons = new AffectIconDictionary();
                foreach (Affect sub in affect.GetIconAffects())
                    _icons.Add(sub);
            }
            if (_items == null)
                _items = new AffectIconItems(16);
            _items.Update(_icons, start);
            _items.Draw();
        }
    }

    /// <summary>
    /// Генерализованная карта чар, приводящая TargetArgs к определенному типу
    /// </summary>
    public abstract class EnchantmentCard<T>: EnchantmentCard {
        public EnchantmentCard(string id): base(id) {
            LogMessage = Resources.Game.CastTargetSpell;
        }

        public sealed override void ManaCostAction(TargetArgs args, ElementValues manas) {
            if (args is TargetArgs<T>)
                ManaCostAction((TargetArgs<T>) args, manas);
            else
                base.ManaCostAction(args, manas);
        }
        public sealed override bool IsPossibleAction(TargetArgs args) {
            if (args is TargetArgs<T>)
                return IsPossibleAction((TargetArgs<T>) args);
            else
                return base.IsPossibleAction(args);
        }
        public sealed override void LogAction(Log log, TargetArgs args) {
            if (args is TargetArgs<T>)
                LogAction(log, (TargetArgs<T>) args);
            else
                base.LogAction(log, args);
        }
        public sealed override void DoAction(TargetArgs args) {
            if (args is TargetArgs<T>)
                DoAction((TargetArgs<T>) args);
            else
                base.DoAction(args);
        }
        public sealed override AbstractObject GetTarget(TargetArgs args) {
            if (args is TargetArgs<T>)
                return GetTarget((TargetArgs<T>) args);
            else
                return base.GetTarget(args);
        }

        protected virtual void ManaCostAction(TargetArgs<T> args, ElementValues manas) {
            base.ManaCostAction(args, manas);
        }
        protected virtual bool IsPossibleAction(TargetArgs<T> args) {
            return base.IsPossibleAction(args);
        }
        protected virtual void LogAction(Log log, TargetArgs<T> args) {
            AbstractObject target = GetTarget(args);
            if (target != null && LogMessage != null)
                log.Add(LogMessage, args.Caster, this, target);
            else
                base.LogAction(log, args);
        }
        protected virtual void DoAction(TargetArgs<T> args) {
            base.DoAction(args);
        }
        protected virtual AbstractObject GetTarget(TargetArgs<T> args) {
            return base.GetTarget(args);
        }
    }

    public abstract class TargetEnchantmentCard<T>: EnchantmentCard<T> where T: AbstractObject {
        public TargetEnchantmentCard(string id): base(id) {}

        protected override AbstractObject GetTarget(TargetArgs<T> args) {
            return args.Target;
        }
    }

    public abstract class SelfEnchantmentCard: EnchantmentCard<int> {
        public SelfEnchantmentCard(string id): base(id) {}

        protected override AbstractObject GetTarget(TargetArgs<int> args) {
            return args.Player;
        }
    }

    public abstract class EnemyEnchantmentCard: EnchantmentCard<int> {
        public EnemyEnchantmentCard(string id): base(id) {}

        protected override AbstractObject GetTarget(TargetArgs<int> args) {
            return args.Player.Enemy;
        }
    }
}
